#include "libutilsconfig.h"
#include "IniFile.h"
#include "CallStack.h"
#include "StringUtils.h"

static tstring string_strip( const tstring& value )
{

	if( !value.size() )
		return value;

	int startPos = value.find_first_not_of(_T(" \t\r\n"));
	int endPos = value.find_last_not_of(_T(" \t\r\n"));

	if( startPos == -1 )
		return value;

	return tstring( value, startPos, endPos - startPos + 1 );


}
LIB_NS_BEGIN
bool isComment( const tstring& line )
{
  if( line.size() == 0 )
    return false;

  return line[0] == _T('#');
}

bool isSection( const tstring& line )
{
  if( line.size() == 0 )
    return false;

  return line[0] == '[' && line[line.size()-1] == ']';
}

tstring splitSection( const tstring& line )
{
  return string_strip(tstring( line, 1, line.size() - 2 ));
}

bool isKeyValue( const tstring& line )
{
  return line.find( '=' ) != tstring::npos;
}

std::pair<tstring, tstring> splitKeyValue( const tstring& line )
{
  int equals = line.find( '=' );
  tstring key = tstring( line, 0, equals );
  tstring value = tstring( line, equals + 1, tstring::npos );
  return std::pair<tstring, tstring>( key, value );
}

std::istream& operator>>( std::istream& stream, IniFile& s )
{
  char buff[1024];
  tstring line;
  IniFile::Sections::iterator section = s.m_sections.end();;

  while( stream.getline(buff, 1024) )
  {
#if defined(UNICODE) || defined(_UNICODE)
	  tstring buffer = UStrConvUtils::StringToWstring(buff,1024);
#else
	tstring buffer = buff;
#endif
    line = string_strip( buffer );
    if( isComment(line) )
    {
      continue;
    }
    else if( isSection(line) )
    {
      section = s.m_sections.insert( s.m_sections.end(), Dictionary(splitSection(line)) );
    }
    else if( isKeyValue(line) )
    {
      std::pair<tstring, tstring> keyValue = splitKeyValue( line );
      if( section == s.m_sections.end() )
        continue;
      (*section).SetString( keyValue.first, keyValue.second );
    }
  }
  return stream;
}

IniFile::Sections IniFile::Get(tstring name ) const
{ QF_STACK_PUSH(IniFile::get)

  Sections sections;
  for ( Sections::size_type i = 0; i < m_sections.size(); ++i )
    if ( m_sections[ i ].GetName() == name )
      sections.push_back( m_sections[ i ] );
  return sections;

  QF_STACK_POP
}
LIB_NS_END
